#include "bsp.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "nwk_api.h"
#include "nwk.h"
#include "bsp_leds.h"
#include "bsp_buttons.h"

#define PERIOD (137)
#define SLEEP_PERIOD (32768)
#define CLOSE (0)
#define OPEN (1)

static uint8_t RxCallBack(linkID_t);

static linkID_t linkID;
uint8_t message[2] = {0,0};
uint8_t length = 0;

uint8_t secondsSlept = 0;
uint8_t gotMessage = 0;


int direction = CLOSE;											// state variable that holds the direction the motor should rotate in
int stop = 0;																// state variable that says when the motor should stop
int motorState = 1;													// holds the value of the stepper coils

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  BSP_Init();
  SMPL_Init(RxCallBack);
  
  P1DIR |= ~(BIT6 + BIT5 + BIT4);           // P1.4, P1.5, P1.6 input 
  P1REN |= (BIT6 + BIT5 + BIT4);						// enable resistors on inputs
  P1OUT |= (BIT6 + BIT5 + BIT4);						// set inputs with pullup resistors
 	P1IES = 0xFF;															// Port 1 interrups triggers on high to low transition
 	P1IE = BIT6 + BIT5 + BIT4;								// P1.4, P1.5, P1.6 interrupt enable
 	P1IFG = 0x00;															// clear port 1 interrupt flags
 	__bis_SR_register(GIE);
  
  TA1CCTL0 = CCIE;                          // CCR0 interrupt enabled
  TA1CCR0 = PERIOD;													// Load cap comp register with step period
  TA1CTL = TASSEL_1 + MC_2;                 // ACLK, contmode
  
  P1OUT |= 1;																// set up stepper motor driver
  
  if(!(P1IN & BIT4))												// if the register is closed...
  {													
  	stop = 1;																// don't try to close it
  	direction = OPEN;
  }
  
  SMPL_Send(SMPL_LINKID_USER_UUD, message, sizeof(message));
	while(SMPL_Link(&linkID) != SMPL_SUCCESS)
	{
		//NWK_DELAY(100);
		SMPL_Send(SMPL_LINKID_USER_UUD, message, sizeof(message));
		BSP_TOGGLE_LED2();
	}
	/*	
	TA1CCTL1 = CCIE;
	TA1CCR1 = SLEEP_PERIOD;
	*/
	while(1)
	{
		uint16_t i = 0;
 	 //__bis_SR_register(LPM0_bits + GIE);
 	 //NWK_DELAY(5000);
 	 SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
 	 SMPL_Send(linkID, message, sizeof(message));
 	 BSP_TOGGLE_LED2();
 	 //NWK_DELAY(100);
 	 //BSP_TURN_OFF_LED2();
 	 for(i = 0; i<64000; i++);
 	 if(gotMessage)
 	 {
	 	 gotMessage = 0;
	 	 SMPL_Receive(linkID, message, &length);
	 	 if(message[0] == direction)
	 	 	stop = 0;														// don't stop, go
 	 }
 	 /*
 	 TA1CCR1 = TA1R + SLEEP_PERIOD;
 	 TA1CCTL1 |= CCIE;
 	 */
	}
}

// Timer A0 interrupt service routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0 (void)
{
	if(stop)																	// if we shouldn't move...
	{
		P1OUT &= ~(0x0F);												// turn off all stepper coils
		return;
	}
	if(direction == OPEN)											// if we need to open...
	{
		motorState <<= 1;												// rotate one stop open
	  if(motorState > 8)
	  	motorState = 1;
	  P1OUT &= ~(0x0F);	  
	  P1OUT |= motorState;
	}
	else 
	{
		motorState >>= 1;												// otherwise we're closing
		if(motorState == 0)											// so close the motor one step
			motorState = 8;
	  P1OUT &= ~(0x0F);	  
	  P1OUT |= motorState;
	}
  TA1CCR0 += PERIOD;                        // Add Offset to CCR0
}

#pragma vector = TIMER1_A1_VECTOR
__interrupt void Timer1_A1(void)
{
	TA1CCR1 += SLEEP_PERIOD;
	if(++secondsSlept == 5)
	{
		secondsSlept = 0;
		TA1CCTL1 &= ~(CCIE);
		LPM0_EXIT;
	}
}


#pragma vector = PORT1_VECTOR
__interrupt void Port1(void)
{
	switch(P1IFG)
	{
		case BIT4:															// closed button has been hit
			if(direction == CLOSE)								// if we were in the closed state... (this is 'debouncing')
			{
				direction = OPEN;										// switch to opening
				stop = 1;														// and stop
			}
			break;
		case BIT5:															// open button has been hit
			if(direction == OPEN)									// if we were in the opened state...
			{
				direction = CLOSE;									// switch to closing
				stop = 1;														// and stop
			}
			break;
		case BIT6:															// toggle button has been hit
			stop = 0;															// so go
			break;
	}
	P1IFG = 0x00;															// clear the register flags
}

static uint8_t RxCallBack(linkID_t lid)
{
	if(lid == linkID)
		gotMessage = 1;
	return 0;
}
